package org.example.mall.admin.service.manage.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.example.mall.admin.mapper.manage.SysTreeMapper;
import org.example.mall.admin.model.entity.manage.SysTree;
import org.example.mall.admin.model.entity.manage.TreeRelation;
import org.example.mall.admin.model.enums.manage.TreeTypeEnum;
import org.example.mall.admin.model.vo.manage.SysTreeVo;
import org.example.mall.admin.service.manage.SysFileService;
import org.example.mall.admin.service.manage.SysLabelService;
import org.example.mall.admin.service.manage.SysTreeService;
import org.example.mall.admin.service.manage.TreeRelationService;
import org.example.mall.admin.util.BusOp;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 系统分类树 服务实现类
 * </p>
 *
 * @author hzq
 * @since 2022-01-08
 */
@Service
@AllArgsConstructor
public class SysTreeServiceImpl extends ServiceImpl<SysTreeMapper, SysTree> implements SysTreeService {

    private final SysFileService sysFileService;
    private final SysLabelService sysLabelService;
    private final TreeRelationService treeRelationService;
    //    private final TransactionTemplate transactionTemplate;
    private final ThreadPoolTaskExecutor applicationTaskExecutor;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean add(SysTree tree) {
//        return transactionTemplate.execute(status -> {
//            BusOp.mustSucceed(save(tree), "添加分类树失败");
//            Boolean relation = treeRelationService.addRelation(tree);
//            asyncCheckAddExtra(tree);
//            return relation;
//        });
        BusOp.mustSucceed(save(tree), "添加分类树失败");
        Boolean relation = treeRelationService.addRelation(tree);
        asyncCheckAddExtra(tree);
        return relation;
    }

    // 新增 检验 extra 扩展字段
    void asyncCheckAddExtra(SysTree tree) {
        applicationTaskExecutor.execute(() -> {
            // 商品分类
            if (TreeTypeEnum.GOODS.getType().equals(tree.getTreeType())) {
                if (StrUtil.isNotBlank(tree.getExtra())) {
                    SysTree sysTree = getById(tree.getTreeId());
                    if (sysTree.getHierarchy() == 3) {
                        sysFileService.asyncLinkFile(tree);
                    } else {
                        getBaseMapper().setExtraIsNull(tree.getTreeId());
                    }
                }
            }
        });
    }

    // 编辑 检验 extra 扩展字段
    void asyncCheckEditExtra(SysTree origin, SysTree target) {
        applicationTaskExecutor.execute(() -> {
            // 商品分类
            if (TreeTypeEnum.GOODS.getType().equals(origin.getTreeType())) {
                SysTree sysTree = getById(target.getTreeId());
                // 层级不为三
                if (sysTree.getHierarchy() != 3) {
                    // 清空扩展字段
                    getBaseMapper().setExtraIsNull(target.getTreeId());
                }
                sysFileService.asyncEditLinkFile(origin, target);
            }
        });
    }

    // 删除 检验 extra 扩展字段
    void syncCheckDelExtra(List<Integer> treeIds) {
        List<SysTree> sysTrees = listByIds(treeIds);
        for (SysTree tree : sysTrees) {
            // 商品分类
            if (TreeTypeEnum.GOODS.getType().equals(tree.getTreeType())) {
                sysFileService.unLinkFileByUrls(tree.getExtra());
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean edit(SysTree tree) {
        SysTree origin = getById(tree.getTreeId());
        BusOp.mustSucceed(updateById(tree), "修改分类树失败");
        // 判断是否需要修改层级 针对单独修改某个字段 提高效率
        if (tree.getParentId() != null) {
            if (!origin.getParentId().equals(tree.getParentId())) {
                TreeRelation relation = new TreeRelation();
                relation.setParentId(tree.getParentId());
                relation.setChildrenId(tree.getTreeId());
                treeRelationService.editRelation(relation);
            }
        }
        asyncCheckEditExtra(origin, tree);
        return Boolean.TRUE;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean del(SysTree tree) {
        List<Integer> ids = treeRelationService.list(Wrappers.<TreeRelation>query()
                .lambda().eq(TreeRelation::getParentId, tree.getTreeId())).stream()
                .map(TreeRelation::getChildrenId).collect(Collectors.toList());
        if (CollUtil.isNotEmpty(ids)) {
            syncCheckDelExtra(ids);
            removeByIds(ids);
        }
        treeRelationService.delRelation(tree.getTreeId());
        delRelation(tree);
        return Boolean.TRUE;
    }

    // 删除相关关联
    void delRelation(SysTree tree) {
        // 商品类目分类
        if (TreeTypeEnum.GOODS.getType().equals(tree.getTreeType())) {
            sysLabelService.delGoodsGroup(tree.getTreeId());
        }
    }

    @Override
    public List<Tree<Integer>> selectTree(SysTree tree) {
        LambdaQueryWrapper<SysTree> wrapper = Wrappers.<SysTree>lambdaQuery()
                .eq(SysTree::getTreeType, tree.getTreeType());
        if (StrUtil.isNotBlank(tree.getExpand())) {
            wrapper.eq(SysTree::getExpand, tree.getExpand());
        }
        if (StrUtil.isNotBlank(tree.getDevelop())) {
            wrapper.eq(SysTree::getDevelop, tree.getDevelop());
        }
        List<TreeNode<Integer>> treeNodes = list(wrapper).stream()
                .filter(sysTree -> sysTree.getTreeId().intValue() != sysTree.getParentId())
                .sorted(Comparator.comparingInt(SysTree::getSort))
                .map(sysTree -> {
                    TreeNode<Integer> treeNode = new TreeNode<>();
                    treeNode.setId(sysTree.getTreeId());
                    treeNode.setParentId(sysTree.getParentId());
                    treeNode.setName(sysTree.getName());
                    treeNode.setWeight(sysTree.getSort());
                    Map<String, Object> extra = new HashMap<>();
                    extra.put("hierarchy", sysTree.getHierarchy());
                    extra.put("sort", sysTree.getSort());
                    extra.put("extra", sysTree.getExtra());
                    extra.put("expand", sysTree.getExpand());
                    extra.put("develop", sysTree.getDevelop());
                    treeNode.setExtra(extra);
                    return treeNode;
                }).collect(Collectors.toList());
        List<Tree<Integer>> build = TreeUtil.build(treeNodes, 0);
        setChildrenIsEmptyList(build, tree);
        return build;
    }

    // 设置子节点为空集合 前端级联选择使用
    void setChildrenIsEmptyList(List<Tree<Integer>> build, SysTree tree) {
        if (tree.getHierarchy() == null) return;
        for (Tree<Integer> node : build) {
            int hierarchy = Integer.parseInt(node.get("hierarchy").toString());
            if (hierarchy >= tree.getHierarchy()) continue;
            List<Tree<Integer>> children = node.getChildren();
            if (CollUtil.isEmpty(children)) {
                node.setChildren(Collections.EMPTY_LIST);
            } else {
                setChildrenIsEmptyList(children, tree);
            }
        }
    }

    @Override
    public SysTreeVo getByTreeId(Integer treeId) {
        return getBaseMapper().getByTreeId(treeId);
    }
}
